using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

namespace Framework
{
    // [CreateAssetMenu]
    public class BundleConfig : ScriptableObject
    {
        private static string ConfigFile = FrameworkSetting.SETTING_FOLDER + "AssetBundleConfig.asset";
        private const string EncryptFilesPath = FrameworkSetting.SETTING_FOLDER + "AssetBundleEncryptFiles.txt";
        private const string BulitinFilesPath = FrameworkSetting.SETTING_FOLDER + "AssetBundleBulitinFiles.txt";
        private const string RawFilesPath = FrameworkSetting.SETTING_FOLDER + "RawFiles.txt";
        // public int Version;
        [Header(" -------- 公共配制 -------- ")]
        public string CustomFolder = "AssetBundles";
        public string BundleExtension = ".assetbundle";

        public string ManifestFile;
        public BuildTarget BuildTarget = BuildTarget.NoTarget;
        //[HideInInspector]
        public string OutputDirectory;
        [Space(4)]
        [Header(" -------- 特殊配制 -------- ")]


        /*
         DisableWriteTypeTree：
             不需要写入字段名，当u3d meta文件有版本变化时会 用到serializedVersion来解析文件
             保持打的资源包和应用包是一个u3d版本即可
             可以大幅减少bundle包的文件大小
             ************编辑器加载bundle资源要禁用DisableWriteTypeTree,不然会有编译器奔溃的问题
         DisableLoadAssetByFileName：
         DisableLoadAssetByFileNameWithExtension：
             可少量减少bundle包的文件大小
             可在加载完后降低cpu耗时，因为不用生成hash值和查询
        */
        public BuildAssetBundleOptions Options =
            BuildAssetBundleOptions.ChunkBasedCompression |
            BuildAssetBundleOptions.DisableLoadAssetByFileName |
            BuildAssetBundleOptions.DisableLoadAssetByFileNameWithExtension;
        [Header("自定义数据")]
        public string UserData;
        [Header("需要加密的文件")]
        public Object EncryptFiles;
        [Header("需要放到内置包的文件")]
        public Object BulitinFiles;
        [Header("原始文件")]
        public Object RawFiles;
        public List<BundleItemData> BundleItems = new List<BundleItemData>();

        private static BundleConfig instance = null;

        public static BundleConfig GetInstance(bool reload = false)
        {
            FrameworkSetting.CreateFolder();
            var instance = getInstance();
            if(instance==null)
            {
                return null;
            }
            bool createFiles = false;
            if (instance.EncryptFiles==null && !File.Exists(EncryptFilesPath))
            {
                createFiles = true;
                File.WriteAllText(EncryptFilesPath, "#指定加密文件,以Assets开始的文件或目录路径");
            }
            if (instance.BulitinFiles==null && !File.Exists(BulitinFilesPath))
            {
                createFiles = true;
                File.WriteAllText(BulitinFilesPath, "#指定内置资源,以Assets开始的文件或目录路径");
            }
            if (instance.RawFiles==null && !File.Exists(RawFilesPath))
            {
                createFiles = true;
                File.WriteAllText(RawFilesPath, "#指定原始资源,目录路径");
            }
            if (createFiles)
            {
                AssetDatabase.Refresh();
                instance.EncryptFiles = AssetDatabase.LoadAssetAtPath<Object>(EncryptFilesPath);
                instance.BulitinFiles = AssetDatabase.LoadAssetAtPath<Object>(BulitinFilesPath);
                instance.RawFiles = AssetDatabase.LoadAssetAtPath<Object>(RawFilesPath);
            }
            return instance;
        }
        private static BundleConfig getInstance()
        {
            if (instance != null)
            {
                instance.OutputDirectory = null;
                return instance;
            }
            if (File.Exists(ConfigFile))
            {
                instance = AssetDatabase.LoadAssetAtPath<BundleConfig>(ConfigFile);
            }
            else
            {

                instance = CreateInstance<BundleConfig>();
                AssetDatabase.CreateAsset(instance, ConfigFile);
            }
            if (instance != null)
            {
                instance.OutputDirectory = null;
                instance.load();
            }
            return instance;
        }

        private void load()
        {

        }
        public void Save()
        {
            if (instance != null)
            {
                EditorUtility.SetDirty(instance);
                AssetDatabase.SaveAssets();
                instance = null;
            }
        }
        public string GetBuildCachePath(string outputPath = "")
        {
            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = OutputDirectory;
            }
            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = Path.GetFullPath(Application.dataPath + "/../output_bundle");
            }
            return (new DirectoryInfo(string.Format("{0}/BuildCache/{1}/", outputPath, BuildTarget.ToString())).FullName);
        }
        public string GetOutputRootPath(string outputPath = "")
        {
            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = OutputDirectory;
            }
            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = Path.GetFullPath(Application.dataPath + "/../output_bundle");
            }
            outputPath = Path.Combine(outputPath, BuildTarget.ToString());
            return (new DirectoryInfo(outputPath).FullName);
        }
        public string GetOutputPath(string outputPath = "")
        {
            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = OutputDirectory;
            }
            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = Path.GetFullPath(Application.dataPath + "/../output_bundle");
            }
            if (string.IsNullOrEmpty(CustomFolder))
            {
                CustomFolder = "AssetBundles";
            }
            outputPath = Path.Combine(outputPath, BuildTarget.ToString(), CustomFolder);
            return new DirectoryInfo(outputPath).FullName;
        }
        public string GetOutputBuiltInPath(string outputPath = "")
        {
            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = OutputDirectory;
            }
            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = Path.GetFullPath(Application.dataPath + "/../output_bundle");
            }
            if (string.IsNullOrEmpty(CustomFolder))
            {
                CustomFolder = "AssetBundles";
            }
            outputPath = Path.Combine(outputPath, BuildTarget.ToString(), "BuiltIn", CustomFolder);
            return (new DirectoryInfo(outputPath).FullName);
        }
        public string GetBundleExtension()
        {
            var ext = BundleExtension;
            if (!ext.StartsWith("."))
            {
                ext = "." + ext;
            }
            return ext;
        }
        public string GetManifestFileName()
        {
            if (!string.IsNullOrEmpty(ManifestFile))
            {
                return ManifestFile;
            }
            return string.Format("{0}.json", BuildTarget.ToString().ToLower());
        }
        public List<string> GetEncryptFiles()
        {
            return GetSettingFiles(this.EncryptFiles);
        }
        public List<string> GetBulitinFiles()
        {
            return GetSettingFiles(this.BulitinFiles);
        }
        public List<string> GetRawFiles()
        {
             return GetSettingFiles(this.RawFiles);
        }
        private List<string> GetSettingFiles(Object target)
        {
            List<string> list = new List<string>();
            if (target != null)
            {
                var assetPath = AssetDatabase.GetAssetPath(target);
                if (File.Exists(assetPath))
                {
                    try
                    {
                        var tmp = Path.Combine(Application.temporaryCachePath, Path.GetFileName(assetPath) + ".txt");
                        File.Copy(assetPath, tmp);
                        var lines = File.ReadAllLines(tmp);
                        var len = lines.Length;
                        for (var i = 0; i < len; i++)
                        {
                            var line = lines[i].Trim();
                            if (line.Length < 1) continue;
                            if (line.StartsWith("#")) continue;
                            list.Add(line);
                        }
                        File.Delete(tmp);
                    }
                    catch (System.Exception e)
                    {
                        Debug.LogException(e);
                    }
                }
            }
            return list;
        }
    }
    [System.Serializable]
    public class BundleItemData
    {
        public Object Source;
        public AssetPackType PackType = AssetPackType.Together;
        public AssetType AssetType = AssetType.Object;
        public string GetName()
        {
            if (Source == null)
            {
                return string.Empty;
            }
            string assetPath = AssetDatabase.GetAssetPath(Source) + "/";
            return assetPath + ":" + AssetType.ToString();
        }
    }
    public enum AssetPackType
    {
        FolderMode,//从文件向上找到的第一个文件夹打一个包
        Together,//当前文件夹打一个包
        FileMode,//每个文件打一个包
        SubFolderMode,//从当前文件夹开始向下找到的第一个文件夹打一个包

    }
    public enum AssetType
    {
        Prefab,
        Texture,
        AudioClip,
        TextAsset,
        Scene,
        Material,
        Shader,
        ScriptableObject,
        _以下类型不常见,
        //以下为不常见类型,没有特殊需求不添加
        Mesh,
        Font,
        Object,
        AnimationClip,
        VideoClip,
        SpriteAtlas,
    }

}